import React, { Component } from "react";
import './AppMain.css';
import { Cobots } from "./AppObject";
import AppRenderer, { loadURDFRobot } from "./AppRenderer";
import logo from './logo.svg';

const ScenesUrl = "./scenes/index.json";
const StreamSources = ['localCamera', 'emulation'];

export default
class AppMain extends Component{
  
  constructor( props ) {
    super( props );

    this.state = {

      allScenes:[],
      hiddenSceneSelector: true,
      hiddenSettingView: false,

      enableTopPanel: false,
      topPanelTarget: "",

      controlPanelTarget: 'cobots',

      cameraWidth: 320,
      cameraHeight: 240,

      mainviewSource:"",
      previewSource:"",

      // Cobots
      cobotsJoints:[],
    }

    this.home = this.home.bind(this);
    this.onCloseTopPanel = this.onCloseTopPanel.bind(this);
    this.onJointValueIncrease = this.onJointValueIncrease.bind(this);
    this.onJointValueDecrease = this.onJointValueDecrease.bind(this);
    this.onSetControlPanel = this.onSetControlPanel.bind(this);
    this.onSetMainView = this.onSetMainView.bind(this);
    this.onLoadSettings = this.onLoadSettings.bind(this);
    this.onLoadScenes = this.onLoadScenes.bind(this);

    this.openLocalCamera = this.openLocalCamera.bind(this);
    this.closeLocalCamera = this.closeLocalCamera.bind(this);

    this.enableStats = this.enableStats.bind(this);

    this.updateCobots = this.updateCobots.bind(this);
    this.updateScene = this.updateScene.bind(this);

    this.videoStream = null;

    this.cobots = new Cobots();
    this.scene = null;

    this.sceneSettings = {};
    this.sceneObjects = {};

  }

  componentDidMount() {

    const defaultObjects = {
      cobots:{
        id:'UR5',
        xyz:[0, 0, 0   ],
        rpy:[-1.57, 0, 0],
      }
    }

    const defaultSettings = {
      enableStats: false,
    }

    this.sceneSettings = defaultSettings;
    this.sceneObjects = defaultObjects;

    this.setState({
      mainviewSource: StreamSources[1],
      previewSource: StreamSources[0],
    })
  }

  componentWillUnmount() {
    this.closeLocalCamera();
  }

  componentDidUpdate() {
    if( this.videoStream ) {
      const video = document.querySelector('video');
      video.srcObject = this.videoStream;
      video.onloadedmetadata = function() {
        video.play();
      };
    }
  }

  refreshWindown() {
    window.location.reload();
  }

  onCloseTopPanel() {
    this.setState({
      enableTopPanel: false,
      topPanelTarget:"",
    })
  }

  onJointValueIncrease( event ) {
    const id = event.target.id;
    this.cobots.jointValueIncrease( id );
  }

  onJointValueDecrease( event ) {
    const id = event.target.id;
    this.cobots.jointValueDecrease( id );
  }

  onSetControlPanel( event ) {
    const id = event.target.id;

    this.setState({
      controlPanelTarget : id,
    })
  }

  onSetMainView( event ) {
    const id = event.target.id;

    switch( id ) {
      case StreamSources[0]:
        this.setState({
          mainviewSource:StreamSources[0],
          previewSource: StreamSources[1],
        })
        break;
      case StreamSources[1]:
        this.setState({
          mainviewSource:StreamSources[1],
          previewSource: StreamSources[0],
        })
        break;
      default:
        break;
    }
  }

  toggleCameraView() {
    const enableCameraView = this.state.enableCameraView;

    // close camera view
    if( enableCameraView ) {
      this.closeLocalCamera();
    }
    else {
      this.openLocalCamera();
    }

  }

  home() {
    window.location.reload();
  }

  onLoadSettings() {
    this.setState({
      enableTopPanel: true,
      topPanelTarget: 'settings'
    })
  }

  onLoadScenes() {

    fetch(ScenesUrl).then( response=>{
      return response.json();
    }).then( json => {
      console.log(">> all scenes:", json)
      this.setState({
        enableTopPanel: true,
        topPanelTarget: 'scene',
        allScenes: json.scenes
      })

    })

  }

  openLocalCamera() {
    this.setState({ enableCameraView: true });

    var constraints = { audio: false, video: {facingMode:'user'},};

    navigator.mediaDevices.getUserMedia(constraints)
    .then((mediaStream) => {
      this.videoStream = mediaStream;
      this.forceUpdate();
    });
  }

  closeLocalCamera() {
    if( this.videoStream ){
      this.videoStream.getTracks().forEach(track=>track.stop());
    }
    this.videoStream = null;
    // this.forceUpdate();
  }

  enableStats( event ) {
    const id = event.target.id;
    const settings = this.sceneSettings;

    if( id === 'open' ) {
      settings["enableStats"] = true;
    }
    else {
      settings["enableStats"] = false;
    }

    this.forceUpdate();
  }

  updateCobots( cobots ) {
    this.cobots.setRobot( cobots );
    this.setState({
      cobotsJoints: this.cobots.joints,
    })
  }

  updateScene ( scene ) {
    this.scene = scene;

    this.initScene();
  }

  initScene() {
    const scene = this.scene;
    console.log(">> 初始化场景物体...");
    if( !scene ) return;
    const objects = this.sceneObjects;

    if( objects.cobots ) {
      
      this.cobots.init( objects.cobots.id );

      loadURDFRobot( scene, objects.cobots, (robot)=>{
        this.updateCobots(robot);
      });
    }
  }

  settingView() {

    return(
      <div className="Flex-Table">
        <div className="group">{"相机配置"}</div>
        <div className="row">
          <div className="cell"><label>{"本地相机"}</label></div>
          <div className="cell">
            <button onClick={this.openLocalCamera}>打开</button>
            <button onClick={this.closeLocalCamera}>关闭</button>
          </div>
        </div>
        <div className="group">{"仿真配置"}</div>
        <div className="row">
          <div className="cell"><label>{"状态指示器"}</label></div>
          <div className="cell">
            <button id='open' onClick={this.enableStats}>打开</button>
            <button id='close' onClick={this.enableStats}>关闭</button>
          </div>
        </div>
      </div>
    );
  }

  sceneSelector() {
    const allScenes = this.state.allScenes;

    return (
      <div className="Flex-Row">
        {allScenes.map((item,key)=>{
          return <div key={key} className="Link-Button">{item.name}</div>
        })}
      </div>
    )
  }

  topPanel() {
    const enable = this.state.enableTopPanel;
    const target = this.state.topPanelTarget;
    if( !enable || !target ) return;
    
    return (
      <div className="Top-Panel">
        {(()=>{
          switch(target){
            case 'scene':
              return this.sceneSelector();
            case 'settings':
              return this.settingView();
            default:
              break;
          }
        })()}
        <button className="close" onClick={this.onCloseTopPanel}>关闭</button>
      </div>
    )
  }

  jointsControl() {
    const joints = this.state.cobotsJoints;
    return joints.map((item, key)=>
      <div key={key} className='row'>
        <div className="cell">{item.name}</div>
        <div className="cell"><input type="text" defaultValue={item.jointValue[0]}/></div>
        <div className="cell"><button id={item.name} onClick={this.onJointValueDecrease}>{"-"}</button></div>
        <div className="cell"><button id={item.name} onClick={this.onJointValueIncrease}>{"+"}</button></div>
      </div>
    )
  }

  controlPanel() {
    const target = this.state.controlPanelTarget;

    switch( target ) {
      case 'cobots':
        return this.jointsControl();
      default:
        return <h1>{target}</h1>
    }
  }

  streamView( src ) {

    switch( src ) {
      case StreamSources[0]:
        return <video className="Camera" poster="./logo192.png"></video>
      case StreamSources[1]:
        return <AppRenderer 
          Settings={this.sceneSettings} 
          // UpdateCobots={this.updateCobots}
          UpdateScene={this.updateScene}
        />
      default:
        return <img src="./logo512.png" alt="logo" />
    }
  }

  render(){

    return (
      <div className="Main">
        {this.topPanel()}
        <div className="Main-Header">
          <img src={logo} alt='logo'></img>
          <h1>{"协作机器人实训平台"}</h1>
        </div>
        <div className="Main-Menu">
          <div className="Menu-Item" onClick={this.home}>{"主页"}</div>
          <div className="Menu-Item" onClick={this.onLoadScenes}>{"场景"}</div>
          <div className="flex-fullfill"></div>

          {/* 主视图切换 */}
          <div className={`Menu-Item ${this.state.mainviewSource === StreamSources[0]?"checked":"unchecked"}`}
            id = {StreamSources[0]}
            onClick={this.onSetMainView}>{"远程视图"}</div>
          <div className={`Menu-Item ${this.state.mainviewSource === StreamSources[1]?"checked":"unchecked"}`}
            id = {StreamSources[1]}
            onClick={this.onSetMainView}>{"仿真视图"}</div> 
                    
          <div className="Menu-Item" onClick={this.onLoadSettings}>{"配置"}</div>
          <div className="Menu-Item">{"帮助"}</div>
          {/* <div className="Menu-Item" onClick={this.refreshWindown.bind(this)}>{"刷新"}</div> */}
        </div>
        <div className="Main-Body">
          <div className="Control-Panel">
            <div className="Panel">{this.controlPanel()}</div>
            <div className="Switches">
              <button id='cobots' className={this.state.controlPanelTarget==='cobots'?"Panel-Checked":"Panel-Unchecked"} onClick={this.onSetControlPanel}>{"协作臂"}</button>
              <button id='system' className={this.state.controlPanelTarget==='system'?"Panel-Checked":"Panel-Unchecked"} onClick={this.onSetControlPanel}>{"系统"}</button>
              <button id='camera' className={this.state.controlPanelTarget==='camera'?"Panel-Checked":"Panel-Unchecked"} onClick={this.onSetControlPanel}>{"相机"}</button>
            </div>            
            <div id='preview' className="Preview">
              {this.streamView( this.state.previewSource )}
            </div>            
          </div>
          <div id='main-view' className="Mainview">
            {this.streamView( this.state.mainviewSource, "main-view" )}
          </div>
        </div>
        <div className="Main-status">
          <label>状态栏</label>
        </div>
      </div>
    );
  }
}